/*
 * NativeAudioDevice.h
 *
 *  Created on: 2018年8月27日
 *      Author: zhengboyuan
 */

#ifndef JNI_NATIVEAUDIODEVICE_H_
#define JNI_NATIVEAUDIODEVICE_H_

#include "AudioDevice.h"
#include "MediaPacketQueue.h"
#include "TimePoint.h"

#include "TCriticalSection.h"
#include "TEvent.h"

#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <SLES/OpenSLES_AndroidConfiguration.h>


namespace av
{

class NativeAudioDevice: public AudioDevice
{
public:
    static void StartUp();
    static void Cleanup();

public:
    NativeAudioDevice();
    virtual ~NativeAudioDevice();

    virtual bool open(int channels, int rate, int bits);
    virtual void close();
    virtual bool isOpen();

    virtual void write(uint8_t* data, int size, int64_t pts);

    virtual float getVolume();

    virtual bool setVolume(float vol);

    virtual bool isMute();

    virtual bool setMute(bool muted);

    virtual void pause(bool toPause);
    virtual void stop();

    virtual void flush();

    virtual bool isPaused();

    virtual int getState();

    virtual void enable(bool enabled);
    virtual bool isEnabled();

    virtual int64_t getCurTime(int64_t* pClock);


    void writeFrame(MediaPacketPtr& frame);


protected:
    static void slBufferQueueCallback(SLAndroidSimpleBufferQueueItf bq, void *context);

    void audioCallback(SLAndroidSimpleBufferQueueItf bq);

    void setState(int state);

protected:
    void clearQueue();
    void cleanup();

    void onNotEnoughData(int length);

    bool openDevice(int sampleRate, int channels);
    void closeDevice();
    bool isDeviceOpen();

    void assign(TimePoint& timePoint, MediaPacketPtr& pkt);
    void saveTime(MediaPacketPtr& frame);

    bool openEngine();
    void closeEngine();

    void setPlayState(int state);

    void markAndSweep(MediaPacketPtr& frame);
    void clearUsedFrames();
    void clearBufferQueue();

    void enqueFrame(MediaPacketPtr& frame, SLAndroidSimpleBufferQueueItf que);

    void startEnqueFrame();

protected:
    comn::CriticalSection    m_cs;

    SLObjectItf m_engineObject;
    SLEngineItf m_engineEngine;

    SLObjectItf m_outputMixObject;
    SLObjectItf m_playerObject;
    SLPlayItf m_playerPlay;
    SLAndroidSimpleBufferQueueItf m_playerBufferQueue;
    SLVolumeItf m_playerVolume;
    SLAndroidConfigurationItf m_playerConfig;

    SLDataFormat_PCM m_pcmFormat;

    int     m_volume;
    bool    m_isMute;

    int     m_state;
    bool    m_enabled;



    TimePoint   m_timePoint;

    MediaPacketQueue m_frameQueue;

    int64_t m_frameCount;
    bool    m_endOfStream;

    comn::Event     m_dataEvent;

    MediaPacketQueue m_usedFrames;

};

} // end of namespace

#endif /* JNI_NATIVEAUDIODEVICE_H_ */
